/*
 * Copyright (c) 2011-2013, fortiss GmbH.
 * Licensed under the Apache License, Version 2.0.
 *
 * Use, modification and distribution are subject to the terms specified
 * in the accompanying license file LICENSE.txt located at the root directory
 * of this software distribution. A copy is available at
 * http://chromosome.fortiss.org/.
 *
 * This file is part of CHROMOSOME.
 *
 * $Id: nodeRegistryController.h 6623 2014-02-05 10:43:23Z wiesmueller $
 */

/**
 * \file
 *         Node Registry Controller.
 */

#ifndef XME_CORE_DIRECTORY_NODEREGISTRYCONTROLLER_H
#define XME_CORE_DIRECTORY_NODEREGISTRYCONTROLLER_H

/**
 * \defgroup core_directory_nodeRegistryController Node Registry Controller group. 
 * @{
 *
 * \brief Node Registry Controller registers all nodes attached to the network.
 *
 * \details The Node Registry Controller stores all associated informations
 *          related to nodes that belong to the Chromosome network. This information
 *          includes at least the node id and the random generated node unique identifier
 *          generated by the connected node.
 */

/******************************************************************************/
/***   Includes                                                             ***/
/******************************************************************************/
#include <stdint.h>

#include "xme/defines.h"

#include "xme/hal/include/graph.h"
#include "xme/hal/include/table.h"
#include "xme/com/interface.h"
#include "xme/core/node.h"
#include "xme/core/topic.h"

/******************************************************************************/
/***   Type definitions                                                     ***/
/******************************************************************************/

/**
 * \struct xme_core_directory_nodeRegistryController_nodeInterfaceIterator_s
 * \typedef xme_core_directory_nodeRegistryController_nodeInterfaceIterator_t
 *
 * \brief The structure to store the node interface iterator.
 */
typedef struct xme_core_directory_nodeRegistryController_nodeInterfaceIterator_s
{
    xme_core_node_nodeId_t nodeId; ///< Node identifier of the node for which the iterator exists.
    xme_core_node_nodeData_t* nodeItem; ///< The nodeData pointer obtained from the node table (xme_core_directory_nodeRegistryController_nodeTable).
    xme_com_interface_addressType_t addressType; ///< Type of interface to iterate over.
    xme_hal_table_rowHandle_t currentHandle; ///< Current row handle till which we have iterated over in the interface table.
    xme_com_interface_address_t* interfaceItem; ///< Pointer to the interface entry to which the currentHandle points.
} xme_core_directory_nodeRegistryController_nodeInterfaceIterator_t;

/**
 * \typedef xme_core_directory_nodeRegistryController_nodeIDIterator_t
 *
 * \brief The nodeID iterator structure.
 */
typedef struct xme_core_directory_nodeRegistryController_nodeIDIterator_s
{
    xme_hal_table_rowHandle_t currentHandle; ///< Handle to the current row in the table xme_core_directory_nodeRegistryController_nodeTable.
} xme_core_directory_nodeRegistryController_nodeIDIterator_t;

/******************************************************************************/
/***   Prototypes                                                           ***/
/******************************************************************************/
XME_EXTERN_C_BEGIN

/**
 * \brief Initializes the Node Registry Controller.
 *
 * \retval XME_STATUS_SUCCESS always.
 */
xme_status_t
xme_core_directory_nodeRegistryController_init(void);

/**
 * \brief Frees all resources associated to the Node Registry Controller.
 */
void
xme_core_directory_nodeRegistryController_fini(void);

/**
 * \brief Registers a new node.
 *
 * \param[in] nodeId Unique identifier of the node to be added.
 * \param[in] nodeName Name of the node to be added.
 * \param[in] guid Globally unique identifier (GUID) of the node to be added.
 *
 * \retval XME_STATUS_SUCCESS if the new node was successfully added.
 * \retval XME_STATUS_INVALID_PARAMETER if nodeId was invalid, nodeName was
 *         NULL or guid was invalid.
 * \retval XME_STATUS_ALREADY_EXIST if a node with the given unique identifier
 *         already exists in the Node Registry.
 * \retval XME_STATUS_OUT_OF_RESOURCES if not enough resources were available
 *         to store the new node.
 */
xme_status_t
xme_core_directory_nodeRegistryController_registerNode
(
    xme_core_node_nodeId_t nodeId,
    const char* nodeName,
    xme_core_node_guid_t guid
);

/**
 * \brief Determines whether the given globally unique identifier (GUID) is
 *        already registered in the Node Registry.
 *
 * \param[in] guid GUID to check.
 * \param[out] outNodeID When non-null and the return value is true
 *             the assigned nodeID will be written here.
 *
 * \return Returns true of guid is already present in the Node Registry
 *         and false otherwise.
 */
bool
xme_core_directory_nodeRegistryController_isNodeGuidRegistered
(
    xme_core_node_guid_t guid,
    xme_core_node_nodeId_t* const outNodeID
);

/**
 * \brief Retrieves the node identifier associated to the given globally unique
 *        identifier (GUID).
 *
 * \param[in] guid GUID of the node to retrieve the identifier for.
 * \param[in,out] outNodeId Address of a variable where to store the node
 *                identifier.
 *
 * \retval XME_STATUS_SUCCESS if the node identifier was successfully obtained.
 * \retval XME_STATUS_INVALID_PARAMETER if guid was invalid or outNodeId was
 *         NULL.
 * \retval XME_STATUS_NOT_FOUND if there are no instances in the node registry
 *         corresponding to the given GUID.
 */
xme_status_t
xme_core_directory_nodeRegistryController_getNodeIdFromGUID
(
    xme_core_node_guid_t guid,
    xme_core_node_nodeId_t* outNodeId
);

/**
 * \brief Retrieves the globally unique identifier (GUID) associated to the
 *        given node identifier.
 *
 * \param[in] nodeId Unique identifier of the node to retrieve the GUID for.
 * \param[in,out] outGuid Address of a variable where to store the GUID.
 *
 * \retval XME_STATUS_SUCCESS if the GUID was successfully obtained.
 * \retval XME_STATUS_INVALID_PARAMETER if nodeId was invalid or outGuid was
 *         NULL.
 * \retval XME_STATUS_NOT_FOUND if there are no instances in the node registry
 *         corresponding to the given nodeId.
 */
xme_status_t
xme_core_directory_nodeRegistryController_getGUIDFromNodeId
(
    xme_core_node_nodeId_t nodeId,
    xme_core_node_guid_t* outGuid
);

/**
 * \brief Retrieves the name of a registered node.
 *
 * \param[in] nodeId Unique identifier of the node whose name to retrieve.
 * \param[out] nodeName Address of the buffer where to store the name of the
 *             node in.
 * \param[in] size Size of the given buffer. If size is too small to store the
 *        whole name, then the name is truncated. The truncation behavior
 *        corresponds to the one from thexme_hal_safeString_strncpy() function.
 *
 * \retval XME_STATUS_SUCCESS if name has been successfully copied to nodeName.
 * \retval XME_STATUS_INVALID_PARAMETER if nodeId was
 *         XME_CORE_NODE_INVALID_NODE_ID or nodeName was NULL.
 * \retval XME_STATUS_NOT_FOUND if no node with given identifier was registered.
 */
xme_status_t
xme_core_directory_nodeRegistryController_getNodeName
(
    xme_core_node_nodeId_t nodeId,
    char* const nodeName,
    uint16_t size
);

/**
 * \brief Adds a new interface address to a node.
 *
 * \param[in] nodeId Unique identifier of the node for which to add the new
 *            interface.
 * \param interfaceAddress Address of the interface to add.
 *
 * \retval XME_STATUS_SUCCESS if the interface address was successfully added
 *         to the node with the given identifier.
 * \retval XME_STATUS_INVALID_PARAMETER if the given node identifier was
 *         invalid.
 * \retval XME_STATUS_NOT_FOUND if the given node identifier was not found.
 * \retval XME_STATUS_ALREADY_EXIST if an interface with the given address
 *         has already been added to the node.
 * \retval XME_STATUS_OUT_OF_RESOURCES if not enough resources were available
 *         to store the new interface address.
 */
xme_status_t
xme_core_directory_nodeRegistryController_addInterface
(
    xme_core_node_nodeId_t nodeId,
    xme_com_interface_address_t interfaceAddress
);

/**
 * \brief Retrieves the address of the first interface of the given type from
 *        the given node.
 *
 * \param[in] nodeId Unique identifier of the node to retrieve the interface
 *            address for.
 * \param[in] addressType Type of interface for which to retrieve the address.
 * \param[in,out] outInterfaceAddress Pointer where the address of the
 *                interface to be returned.
 *
 * \retval XME_STATUS_SUCCESS if an interface was found for the given node
 *         identifier and address type.
 * \retval XME_STATUS_INVALID_PARAMETER if nodeId or addressType was invalid
 *         or outInterfaceAddress was NULL.
 * \retval XME_STATUS_NOT_FOUND if the given node identifier does not exist
 *         or no interface of the given type does not exist.
 */
xme_status_t
xme_core_directory_nodeRegistryController_getInterface
(
    xme_core_node_nodeId_t nodeId,
    xme_com_interface_addressType_t addressType,
    xme_com_interface_address_t** outInterfaceAddress
);

/**
 * \brief Initializes a node interface iterator.
 *
 * \details If the function returns successfully, the iterator points to the
 *          first node interface of the given type in the Node Registry
 *          Controller.
 *
 * \param[in] nodeId Unique identifier of the node whose interfaces to iterate
 *            over.
 * \param[in] addressType Type of interface to iterate upon. The special value
 *            XME_COM_INTERFACE_ADDRESS_TYPE_INVALID can be used to iterate
 *            over all interface types.
 * \param[in,out] iterator Address of the iterator to be initialized.
 *
 * \retval XME_STATUS_SUCCESS if the iterator was successfully initialized.
 * \retval XME_STATUS_INVALID_PARAMETER if iterator is NULL.
 * \retval XME_STATUS_NOT_FOUND if the given node ID was invalid.
 * \retval XME_STATUS_OUT_OF_RESOURCES if not enough resources were available
 *         to initialize the iterator.
 */
xme_status_t
xme_core_directory_nodeRegistryController_initNodeInterfaceIterator
(
    xme_core_node_nodeId_t nodeId,
    xme_com_interface_addressType_t addressType,
    xme_core_directory_nodeRegistryController_nodeInterfaceIterator_t** iterator
);

/**
 * \brief Returns whether the given node interface iterator has a next element.
 *
 * \note Does not change the iterator state.
 *
 * \note The iterator must have been previously initialized via
 *       xme_core_directory_nodeRegistryController_initNodeInterfaceIterator().
 *
 * \param[in] iterator Iterator to check for next element.
 *
 * \return Returns true if the iterator was not NULL and has a next element
 *         and false otherwise.
 */
bool
xme_core_directory_nodeRegistryController_hasNextInterface
(
    const xme_core_directory_nodeRegistryController_nodeInterfaceIterator_t* const iterator
);

/**
 * \brief Retrieves the address of the next interface from the given iterator.
 *
 * \note Before calling this function, make sure to call
 *       xme_core_directory_nodeRegistryController_hasNextInterface()
 *       to check whether the iterator has a next element.
 *
 * \note The iterator must have been previously initialized via
 *       xme_core_directory_nodeRegistryController_initNodeInterfaceIterator().
 *
 * \param[in] iterator Iterator to retrieve next interface from.
 *
 * \return On success, a non-NULL value that corresponds to the address of the
 *         next interface from the given iterator. NULL if iterator was NULL.
 */
xme_com_interface_address_t*
xme_core_directory_nodeRegistryController_nextInterface
(
    xme_core_directory_nodeRegistryController_nodeInterfaceIterator_t *iterator
);

/**
 * \brief Finalizes the given node interface iterator.
 *
 * \note The iterator must have been previously initialized via
 *       xme_core_directory_nodeRegistryController_initNodeInterfaceIterator().
 *
 * \param[in] iterator Address of the iterator to finalize.
 *
 * \retval XME_STATUS_SUCCESS if the iterator has been successfully finalized.
 * \retval XME_STATUS_INVALID_PARAMETER if iterator was NULL.
 */
xme_status_t
xme_core_directory_nodeRegistryController_finiNodeInterfaceIterator
(
    xme_core_directory_nodeRegistryController_nodeInterfaceIterator_t* iterator
);

/**
 * \brief Initializes a node ID iterator.
 *
 * \details If the function returns successfully, the iterator points to the
 *          first node identifier in the Node Registry Controller.
 *
 * \param[in,out] iterator Iterator to be initialized.
 *
 * \retval XME_STATUS_SUCCESS if the iterator was successfully initialized.
 * \retval XME_STATUS_INVALID_PARAMETER if iterator is NULL.
 */
xme_status_t
xme_core_directory_nodeRegistryController_initNodeIDIterator
(
    xme_core_directory_nodeRegistryController_nodeIDIterator_t* iterator
);

/**
 * \brief Returns whether the given node ID iterator has a next element.
 *
 * \note Does not change the iterator state.
 *
 * \note The iterator must have been previously initialized via
 *       xme_core_directory_nodeRegistryController_initNodeIDIterator().
 *
 * \param[in] iterator Iterator to check for next element.
 *
 * \return Returns true if the iterator has a next element
 *         and false otherwise.
 */
bool
xme_core_directory_nodeRegistryController_hasNextNodeID
(
    const xme_core_directory_nodeRegistryController_nodeIDIterator_t* const iterator
);

/**
 * \brief Retrieves the next node ID from the given iterator.
 *
 * \note Before calling this function, make sure to call
 *       xme_core_directory_nodeRegistryController_hasNextNodeID()
 *       to check whether the iterator has a next element.
 *
 * \note The iterator must have been previously initialized via
 *       xme_core_directory_nodeRegistryController_initNodeIDIterator().
 *
 * \param[in] iterator Iterator to retrieve next node ID from.
 *
 * \return On success, a nonzero value that corresponds to the next node ID
 *         from the given iterator. XME_CORE_NODE_INVALID_NODE_ID if the given
 *         iterator was invalid.
 */
xme_core_node_nodeId_t
xme_core_directory_nodeRegistryController_nextNodeID
(
    xme_core_directory_nodeRegistryController_nodeIDIterator_t* const iterator
);

/**
 * \brief Finalizes the given node ID iterator.
 *
 * \note The iterator must have been previously initialized via
 *       xme_core_directory_nodeRegistryController_initNodeIDIterator().
 *
 * \param[in] iterator Iterator to finalize.
 *
 * \retval XME_STATUS_SUCCESS if the iterator has been successfully finalized.
 * \retval XME_STATUS_INVALID_PARAMETER if iterator was NULL.
 */
xme_status_t
xme_core_directory_nodeRegistryController_finiNodeIDIterator
(
    xme_core_directory_nodeRegistryController_nodeIDIterator_t* iterator
);

/**
 * \brief Deregisters a node from the Node Registry Controller.
 *
 * \details The deregistration of the node removes it from the list of known
 *          nodes in the ecosystem.
 *
 * \param[in] nodeID Unique identifier of the node to deregister.
 *
 * \retval XME_STATUS_SUCCESS if the node has been successfully deregistered
 *         from the Node Registry Controller.
 * \retval XME_STATUS_INVALID_PARAMETER if the given node identifier was
 *         invalid.
 * \retval XME_STATUS_NOT_FOUND if the node is not registered in the
 *         Node Registry Controller.
 */
xme_status_t
xme_core_directory_nodeRegistryController_deregisterNode
(
    xme_core_node_nodeId_t nodeID
);

XME_EXTERN_C_END

/**
 * @}
 */

#endif // #ifndef XME_CORE_DIRECTORY_NODEREGISTRYCONTROLLER_H
